// RUN: not mlir-pdll %s -I %S -I %S/../../../include -split-input-file 2>&1 | FileCheck %s

//===----------------------------------------------------------------------===//
// Reference Expr
//===----------------------------------------------------------------------===//

Pattern {
  // CHECK: expected identifier constraint
  let foo = Foo: ;
}

// -----

Pattern {
  // CHECK: undefined reference to `bar`
  let foo = bar;
}

// -----

Pattern FooPattern {
  erase _: Op;
}

Pattern {
  // CHECK: invalid reference to `FooPattern`
  let foo = FooPattern;
}

// -----

Pattern {
  // CHECK: expected `:` after `_` variable
  let foo = _;
}

// -----

Pattern {
  // CHECK: expected identifier constraint
  let foo = _: ;
}

// -----

//===----------------------------------------------------------------------===//
// Call Expr
//===----------------------------------------------------------------------===//

Constraint foo(value: Value);

Pattern {
  // CHECK: expected `)` after argument list
  foo(_: Value{};
}

// -----

Pattern {
  // CHECK: expected a reference to a callable `Constraint` or `Rewrite`, but got: `Op`
  let foo: Op;
  foo();
}

// -----

Constraint Foo();

Pattern {
  // CHECK: invalid number of arguments for constraint call; expected 0, but got 1
  Foo(_: Value);
}

// -----

Constraint Foo(arg: Value);

Pattern {
  // CHECK: unable to convert expression of type `Attr` to the expected type of `Value`
  Foo(attr<"i32">);
}

// -----

//===----------------------------------------------------------------------===//
// Member Access Expr
//===----------------------------------------------------------------------===//

Pattern {
  // CHECK: expected identifier or numeric member name
  let root: Op;
  erase root.<>;
}

// -----

Pattern {
  // CHECK: invalid member access `unknown_result` on expression of type `Op`
  let root: Op;
  erase root.unknown_result;
}

// -----

Pattern {
  let tuple = (result1 = value: Value, result2 = value);

  // CHECK: invalid member access `unknown_result` on expression of type `Tuple<result1: Value, result2: Value>`
  let tuple2 = (tuple.result1, tuple.unknown_result);

  erase op<>;
}

// -----

Pattern {
  let tuple = (result1 = value: Value, result2 = value);

  // CHECK: invalid member access `2` on expression of type `Tuple<result1: Value, result2: Value>`
  let tuple2 = (tuple.0, tuple.2);

  erase op<>;
}

// -----

//===----------------------------------------------------------------------===//
// Range Expr
//===----------------------------------------------------------------------===//

Pattern {
  // CHECK: unable to convert expression of type `Tuple<>` to the expected type of `ValueRange`
  // CHECK: Tuple to Range conversion is currently only allowed within a rewrite context
  erase op<>(());
}

// -----

Pattern {
  // CHECK: unable to convert expression of type `Tuple<Value, Type>` to the expected type of `ValueRange`
  replace op<>(arg: Value) -> (type: Type) with op<test.op>((arg, type));
}

// -----

//===----------------------------------------------------------------------===//
// Tuple Expr
//===----------------------------------------------------------------------===//

Pattern {
  // CHECK: expected `)` after tuple element list
  let tuple = (value: Value, value;
}

// -----

Pattern {
  // CHECK: unable to build a tuple with `Tuple<Value, Value>` element
  let tuple = (_: Value, _: Value);
  let var = (tuple);
  erase op<>;
}

// -----

Constraint Foo();

Pattern {
  // CHECK: unable to build a tuple with `Constraint` element
  let tuple = (Foo);
  erase op<>;
}

// -----

Rewrite Foo();

Pattern {
  // CHECK: unable to build a tuple with `Rewrite` element
  let tuple = (Foo);
  erase op<>;
}

// -----

Pattern {
  // CHECK: expected expression
  let tuple = (10 = _: Value);
  erase op<>;
}

// -----

Pattern {
  // CHECK: duplicate tuple element label `field`
  // CHECK: see previous label use here
  let tuple = (field = _: Value, field = _: Value);
  erase op<>;
}

// -----

//===----------------------------------------------------------------------===//
// `attr` Expr
//===----------------------------------------------------------------------===//

Pattern {
  // CHECK: expected string literal containing MLIR attribute
  let foo = attr<foo>;
}

// -----

Pattern {
  // CHECK: expected `>` after attribute literal
  let foo = attr<""<>;
}

// -----

//===----------------------------------------------------------------------===//
// `op` Expr
//===----------------------------------------------------------------------===//

Pattern {
  // CHECK: expected `)` after operation operand list
  let value: Value;
  let foo = op<func.func>(value<;
}

// -----

Pattern {
  // CHECK: unable to convert expression of type `Attr` to the expected type of `ValueRange`
  let attr: Attr;
  let foo = op<func.func>(attr);
}

// -----

Pattern {
  // CHECK: expected `Value` or `ValueRange` convertible expression, but got `Type`
  let foo = op<>(_: Type, _: TypeRange);
}

// -----

Pattern {
  // CHECK: expected identifier or string attribute name
  let foo = op<> { 10;
}

// -----

Pattern {
  // CHECK: expected `Attr` expression, but got `Value`
  let foo = op<> { foo = _: Value };
}

// -----

Pattern {
  // CHECK: expected `}` after operation attribute list
  let foo = op<> { "foo" {;
}

// -----

Pattern {
  // CHECK: expected `(` before operation result type list
  let foo = op<> -> );
}

// -----

Pattern {
  // CHECK: unable to convert expression of type `ValueRange` to the expected type of `TypeRange`
  let foo = op<> -> (_: ValueRange);
}

// -----

Pattern {
  // CHECK: expected `Type` or `TypeRange` convertible expression, but got `Value`
  let foo = op<> -> (_: Value, _: ValueRange);
}

// -----

Pattern {
  // CHECK: expected `)` after operation result type list
  let value: TypeRange;
  let foo = op<> -> (value<;
}

// -----

#include "include/ops.td"

Pattern {
  // CHECK: invalid number of operand groups for `test.all_empty`; expected 0, but got 2
  // CHECK: see the definition of `test.all_empty` here
  let foo = op<test.all_empty>(operand1: Value, operand2: Value);
}

// -----

#include "include/ops.td"

Pattern {
  // CHECK: invalid number of result groups for `test.all_empty`; expected 0, but got 2
  // CHECK: see the definition of `test.all_empty` here
  let foo = op<test.all_empty> -> (result1: Type, result2: Type);
}

// -----

Pattern {
  // CHECK: warning: operation result types are marked to be inferred, but
  // CHECK-SAME: `test.unknown_inferred_result_op` is unknown.
  // CHECK-SAME: Ensure that `test.unknown_inferred_result_op` supports zero
  // CHECK-SAME: results or implements `InferTypeOpInterface`.
  // CHECK-SAME: Include the ODS definition of this operation to remove this
  // CHECK-SAME: warning.
  rewrite _: Op with {
    op<test.unknown_inferred_result_op>;
  };
}

// -----

#include "include/ops.td"

Pattern {
  // CHECK: warning: operation result types are marked to be inferred, but
  // CHECK-SAME: `test.multiple_single_result` does not provide an implementation
  // CHECK-SAME: of `InferTypeOpInterface`. Ensure that `test.multiple_single_result`
  // CHECK-SAME: attaches `InferTypeOpInterface` at runtime, or add support
  // CHECK-SAME: to the ODS definition to remove this warning.
  // CHECK: see the definition of `test.multiple_single_result` here
  rewrite _: Op with {
    op<test.multiple_single_result>;
  };
}

// -----

//===----------------------------------------------------------------------===//
// `type` Expr
//===----------------------------------------------------------------------===//

Pattern {
  // CHECK: expected string literal containing MLIR type
  let foo = type<foo;
}

// -----

Pattern {
  // CHECK: expected `>` after type literal
  let foo = type<"";
}
